﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AnalysisServices;

namespace ASPermissions
{
    public class Amo
    {
        public Server Server {get; set;}
        public Database Database {get; set;}
        //public Cube Cube {get; set;}

        public Amo (string server, string database)//, string cube)
        {
            try
            {
                //Server
                this.Server = new Server();
                this.Server.Connect(server);
                //Database
                this.Database = this.Server.Databases.FindByName(database);
                //Cube
                //this.Cube = this.Database.Cubes.FindByName(cube);
            }
            catch (OutOfMemoryException memoryException)
            {
                throw new OutOfMemoryException("ERROR: Constructor failed with out of memory. The exception message is " + memoryException.Message);
            }
            catch (ConnectionException serverNotFoundException)
            {
                throw new ConnectionException("ERROR: Unable to connect to Analysis Server " + server + "Connection failed with error message: " + serverNotFoundException.Message);
            }
            catch (ArgumentNullException argNullException)
            {
                if (server == null)
                {
                    throw new AmoException("ERROR: server parameter supplied with NULL value to constructor");
                }
                if (database == null)
                {
                    throw new AmoException("ERROR: database parameter supplied with NULL value to constructor");
                }
                //if (cube == null)
                //{
                //    throw new AmoException("ERROR: cube paramener supplied with NULL value to constructor");
                //}
                throw argNullException;
            }
            //catch (OperationException opException)
            //{
            //    throw new AmoException("ERROR: Constructor failed with exception " + opException.Message + ". Parameters passed were server=" + server + ",database=" +
            //                            database + ",cube=" + cube);
            //}
            catch (AmoException genericAmoException)
            {
                if (this.Database == null)
                {
                    throw new AmoException("ERROR: Unable to connect to Database " + database + "on " + server);
                }
                //if (this.Cube == null)
                //{
                //    throw new AmoException("ERROR: Unable to connect to Cube " + cube + "within " + database + "on " + server);
                //}
                throw genericAmoException;
            }
        }
        public int ListAllRolesAndMembers()
        {
            int retVal = 0;

            try
            {
                ListAllServerUsers();

                Console.WriteLine("Database: [{0}]", this.Database.ToString());
                Console.WriteLine("|--Roles");

                //List<Role>              roles       = new List<Role>();
                DatabasePermission          dbperm;
                DataSourcePermission        dsperm      = new DataSourcePermission();
                CubePermission              cubeperm    = new CubePermission();
                DimensionPermission         dimperm     = new DimensionPermission();
                MiningStructurePermission   minperm     = new MiningStructurePermission();

                foreach (Role role in this.Database.Roles)
                {

                    dbperm = this.Database.DatabasePermissions.GetByRole(role.ID);

                    Console.WriteLine("  |--[{0}]: [Admin: {1}; ReadDefinition: {2}; ProcessDatabase: {3}]", role.ToString(), dbperm.Administer.ToString(), dbperm.ReadDefinition.ToString(), dbperm.Process.ToString());
                    
                    Console.WriteLine("   |--[Users]");
                    foreach (RoleMember member in role.Members)
                    {
                        Console.WriteLine("    |--[{0}]", member.Name);
                    }

                    if (!dbperm.Administer)
                    {

                        Console.WriteLine("   |--[DataSources]");
                        foreach (DataSource ds in this.Database.DataSources)
                        {
                            Console.WriteLine("    |--[{0}]: ReadAcess: {1}, ReadDefinition: {2}", ds.Name, dbperm.Read, dbperm.ReadDefinition);
                        }

                        Console.WriteLine("   |--[Cubes]");
                        foreach (Cube cube in this.Database.Cubes)
                        {
                            Console.WriteLine("    |--[{0}]: Read: {1} | Write: {2}, Process: {3}", cube.Name, cubeperm.Read, cubeperm.Write, cubeperm.Process.ToString());
                            //foreach (MeasureGroup mgroup in cube.MeasureGroups)
                            //{
                            //    Console.WriteLine("     |--[{0}]", mgroup.Name);
                            //}
                        }

                        Console.WriteLine("   |--[Dimensions]");
                        foreach (Dimension dim in this.Database.Dimensions)
                        {
                            Console.WriteLine("    |--[{0}]: Read: {1} | Write: {2}, ReadDefition: {3}, Process: {4}", dim.Name, dimperm.Read, dimperm.Write, dimperm.ReadDefinition, dimperm.Process.ToString());
                        }

                        Console.WriteLine("   |--[Mining Structures]");
                        foreach(MiningStructure mining in this.Database.MiningStructures)
                        {
                            Console.WriteLine("    |--[{0}]: Read: {1} | Write: {2}, ReadDefinition: {3}, Process: {4}", mining.Name, minperm.Read, minperm.Write, minperm.ReadDefinition, minperm.Process.ToString());
                        }
                    }

                    retVal++;
                }
            }
            catch (OutOfMemoryException memoryException)
            {
                throw new OutOfMemoryException("ERROR: There is sufficient memory to list All Roles " + memoryException.Message);
            }
            catch (ConnectionException serverNotFound)
            {
                throw new ConnectionException("ERROR: Unable to connect to Analysis Server: " + this.Server + 
                                            " - Connection failed with the error message " + serverNotFound.Message);
            }
            catch (OperationException OpException)
            {
                throw new AmoException("ERROR: ListAllRolesAndMembers() failed with exception " + OpException.Message);
            }
            catch (AmoException GenericAmoException)
            {
                throw GenericAmoException;
            }
               return retVal;
        }

        public void ListAllServerUsers()
        {            
            Console.WriteLine("Server: [{0}], Version: [{1} - {2}], Edition: [{3}]", this.Server.ToString(), this.Server.Version, this.Server.ProductLevel, this.Server.Edition);

            Console.WriteLine("[Server Role]");
            foreach(Role roleadm in this.Server.Roles)
            {
                Console.WriteLine("  |--[{0}]", roleadm.Name);

                foreach(RoleMember memberadmin in roleadm.Members)
                {
                    Console.WriteLine("   |--[{0}]", memberadmin.Name);
                }

            }
        }
    }
}
